//
//  String+Extension.swift
//  FrameProduct
//
//  Created by delegate on 2024/2/3.
//

import UIKit
import CommonCrypto

public extension LXS where Base: StringProtocol {
    /// 验证手机号
    var isPhoneNumber: Bool {
        let mobile = "^1(3[0-9]|5[0-35-9]|8[025-9])\\d{8}$"
        let  CM = "^1(34[0-8]|(3[5-9]|5[017-9]|8[278])\\d)\\d{7}$"
        let  CU = "^1(3[0-2]|5[256]|8[56])\\d{8}$"
        let  CT = "^1((33|53|8[09])[0-9]|349)\\d{7}$"
        let regextestmobile = NSPredicate(format: "SELF MATCHES %@",mobile)
        let regextestcm = NSPredicate(format: "SELF MATCHES %@",CM )
        let regextestcu = NSPredicate(format: "SELF MATCHES %@",CU)
        let regextestct = NSPredicate(format: "SELF MATCHES %@",CT)
        if ((regextestmobile.evaluate(with: base) == true)
                || (regextestcm.evaluate(with: base)  == true)
                || (regextestct.evaluate(with: base) == true)
                || (regextestcu.evaluate(with: base) == true))
        {
            return true
        }
        else {
            return false
        }
    }
    
    /// 验证手机号
    /// 简单点就看是否是1开头的数字吧
    var isPhoneNumber1: Bool {
        let mobileReg = "^1\\d{10}$"
        let regextestmobile = NSPredicate(format: "SELF MATCHES %@",mobileReg)
        return regextestmobile.evaluate(with: base)
    }
    ///验证是否是邮箱
    var isEmail: Bool {
        let emailReg = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$"
        let regextestEmail = NSPredicate(format: "SELF MATCHES %@",emailReg)
        return regextestEmail.evaluate(with: base)
    }
    
    ///只允许输入中文、数字、字母
    var isRemark: Bool {
        let match: String = "(^[^a-zA-Z0-9\\u4e00-\\u9fa5]+$)"
        let predicate = NSPredicate(format: "SELF matches %@", match)
        return predicate.evaluate(with: base)
    }
    
    /// 验证密码
    /// 密码正则  8-16位字母和数字组合
    var isPasswordRuler: Bool {
        let passwordRule = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z[_#@]+$)]{8,16}$"
        let regexPassword = NSPredicate(format: "SELF MATCHES %@",passwordRule)
        if regexPassword.evaluate(with: base) == true {
            return true
        }
        else {
            return false
        }
    }
    
    /// 文本中是否有包含字母的字符
//    var isContainsLetters: Bool {
//        let index = base.firstIndex { chr in
//            return (chr >= "a" && chr <= "z") || (chr >= "A" && chr <= "Z")
//        }
//       return index != nil
//    }
    
    /// 取出文本中的所有字母字符串
    var letters: [String] {
       return base.compactMap { chr -> String? in
            if (chr >= "a" && chr <= "z") || (chr >= "A" && chr <= "Z") == true {
                return String(chr)
            }
            return nil
        }
    }
    
    /// 文本中是否有包含字母的字符
    var isContainsLetters: Bool {
        // 匹配字符串中的所有字母
        let pattern = "^[a-zA-Z]+"
        let predicate = NSPredicate(format: "SELF MATCHES %@", pattern)
        return predicate.evaluate(with: base)
    }
    
    /// 是否为纯数字
    var isOnlyDigits: Bool {
        let pattern = "^[0-9]+$"
        let regexPassword = NSPredicate(format: "SELF MATCHES %@", pattern)
        return regexPassword.evaluate(with: base)
    }
    
    /// 是否为纯字母
    var isOnlyLetters: Bool {
        // 匹配字符串中的所有字母
        let pattern = "^[a-zA-Z]+$"
        let predicate = NSPredicate(format: "SELF MATCHES %@", pattern)
        return predicate.evaluate(with: base)
    }
    
    /// 是否为纯特殊字符
    func isOnlySpecCharacters(_ specCharacters: String? = nil) -> Bool {
        // ~!@#$%^&*()[]{}<>?\+
        // 特殊字符, 特定的
        var _specCharacters = specCharacters
        if _specCharacters == nil {
            _specCharacters = "~!@#$%^&*\\(\\)\\[\\]\\{\\}<>\\?\\+"
        }
        let pattern = "^[\(_specCharacters!)]+$"
        let predicate = NSPredicate(format: "SELF MATCHES %@", pattern)
        return predicate.evaluate(with: base)
    }
    
//    /// 文本中是否有包含数字的字符
//    var isContainsDigits: Bool {
//        let stringArray = base.components(separatedBy: CharacterSet.decimalDigits.inverted)
//        let index = stringArray.firstIndex {
//            return Int($0) != nil
//        }
//        return index != nil
//    }
    /// 取出文本中的所有数字字符串
    var digits: [Int] {
        let stringArray = base.components(separatedBy: CharacterSet.decimalDigits.inverted)
        return stringArray.compactMap { chr -> Int? in
            return Int(chr)
        }
    }
    
    /// 是否包含数字
    var isContainsDigits: Bool {
        // 匹配字符串中的所有数字
        let digits = "^[0-9]+"
        let predicate = NSPredicate(format: "SELF MATCHES %@", digits)
        return predicate.evaluate(with: base)
    }
    /// 验证中文姓名
    var isChineseName: Bool {
        let match: String = "(^[\\u4e00-\\u9fa5]+$)"
        let predicate = NSPredicate(format: "SELF matches %@", match)
        return predicate.evaluate(with: base)
    }
    
    /// 昵称
    var isNickName: Bool {
        let pattern = "(^[\\u4E00-\\u9FA5A-Za-z0-9]+$)"
        let predicate = NSPredicate(format: "SELF MATCHES %@", pattern)
        return predicate.evaluate(with: base)
    }
    
    /// 验证身份证号（ id card ）
    var isTrueIDNumber: Bool {
        guard var value = base as? String else {
            return false
        }
        value = value.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        var length : Int = 0
        length = value.count
        if length != 15 && length != 18{
            //不满足15位和18位，即身份证错误
            return false
        }
        // 省份代码
        let areasArray = ["11","12", "13","14", "15","21", "22","23", "31","32", "33","34", "35","36", "37","41", "42","43", "44","45", "46","50", "51","52", "53","54", "61","62", "63","64", "65","71", "81","82", "91"]
        // 检测省份身份行政区代码
//        let index = value.index(value.startIndex, offsetBy: 2)
//        let valueStart2 = value.substring(to: index)
//        let i = value[value.startIndex..<value.index(value.startIndex, offsetBy: 2)]
        let valueStart2 = value.lxs.subString(start: 0, end: 2)

        //标识省份代码是否正确
        var areaFlag = false
        for areaCode in areasArray {
            if areaCode == valueStart2 {
                areaFlag = true
                break
            }
        }
        if !areaFlag {
            return false
        }
        var regularExpression : NSRegularExpression?
        var numberofMatch : Int?
        var year = 0
        switch length {
        case 15:
            //获取年份对应的数字
            let valueNSStr = value as NSString
            let yearStr = valueNSStr.substring(with: NSRange.init(location: 6, length: 2)) as NSString
            year = yearStr.integerValue + 1900
            if year % 4 == 0 || (year % 100 == 0 && year % 4 == 0) {
                //创建正则表达式 NSRegularExpressionCaseInsensitive：不区分字母大小写的模式
                //测试出生日期的合法性
                regularExpression = try! NSRegularExpression.init(pattern: "^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$", options: NSRegularExpression.Options.caseInsensitive)
            }else{
                //测试出生日期的合法性
                regularExpression = try! NSRegularExpression.init(pattern: "^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$", options: NSRegularExpression.Options.caseInsensitive)
            }
            numberofMatch = regularExpression?.numberOfMatches(in: value, options: NSRegularExpression.MatchingOptions.reportProgress, range: NSRange.init(location: 0, length: value.count))
            if numberofMatch! > 0 {
                return true
            }else{
                return false
            }
        case 18:
            let valueNSStr = value as NSString
            let yearStr = valueNSStr.substring(with: NSRange.init(location: 6, length: 4)) as NSString
            year = yearStr.integerValue
            if year % 4 == 0 || (year % 100 == 0 && year % 4 == 0) {
                //测试出生日期的合法性
                regularExpression = try! NSRegularExpression.init(pattern: "^((1[1-5])|(2[1-3])|(3[1-7])|(4[1-6])|(5[0-4])|(6[1-5])|71|(8[12])|91)\\d{4}(((19|20)\\d{2}(0[13-9]|1[012])(0[1-9]|[12]\\d|30))|((19|20)\\d{2}(0[13578]|1[02])31)|((19|20)\\d{2}02(0[1-9]|1\\d|2[0-8]))|((19|20)([13579][26]|[2468][048]|0[048])0229))\\d{3}(\\d|X|x)?$", options: NSRegularExpression.Options.caseInsensitive)
                
            }else{
                //测试出生日期的合法性
                regularExpression = try! NSRegularExpression.init(pattern: "^((1[1-5])|(2[1-3])|(3[1-7])|(4[1-6])|(5[0-4])|(6[1-5])|71|(8[12])|91)\\d{4}(((19|20)\\d{2}(0[13-9]|1[012])(0[1-9]|[12]\\d|30))|((19|20)\\d{2}(0[13578]|1[02])31)|((19|20)\\d{2}02(0[1-9]|1\\d|2[0-8]))|((19|20)([13579][26]|[2468][048]|0[048])0229))\\d{3}(\\d|X|x)?$", options: NSRegularExpression.Options.caseInsensitive)
                
            }
            numberofMatch = regularExpression?.numberOfMatches(in: value, options: NSRegularExpression.MatchingOptions.reportProgress, range: NSRange.init(location: 0, length: value.count))
            
            if numberofMatch! > 0 {
                let a = getStringByRangeIntValue(Str: valueNSStr, location: 0, length: 1) * 7
                let b = getStringByRangeIntValue(Str: valueNSStr, location: 10, length: 1) * 7
                let c = getStringByRangeIntValue(Str: valueNSStr, location: 1, length: 1) * 9
                let d = getStringByRangeIntValue(Str: valueNSStr, location: 11, length: 1) * 9
                let e = getStringByRangeIntValue(Str: valueNSStr, location: 2, length: 1) * 10
                let f = getStringByRangeIntValue(Str: valueNSStr, location: 12, length: 1) * 10
                let g = getStringByRangeIntValue(Str: valueNSStr, location: 3, length: 1) * 5
                let h = getStringByRangeIntValue(Str: valueNSStr, location: 13, length: 1) * 5
                let i = getStringByRangeIntValue(Str: valueNSStr, location: 4, length: 1) * 8
                let j = getStringByRangeIntValue(Str: valueNSStr, location: 14, length: 1) * 8
                let k = getStringByRangeIntValue(Str: valueNSStr, location: 5, length: 1) * 4
                let l = getStringByRangeIntValue(Str: valueNSStr, location: 15, length: 1) * 4
                let m = getStringByRangeIntValue(Str: valueNSStr, location: 6, length: 1) * 2
                let n = getStringByRangeIntValue(Str: valueNSStr, location: 16, length: 1) * 2
                let o = getStringByRangeIntValue(Str: valueNSStr, location: 7, length: 1) * 1
                let p = getStringByRangeIntValue(Str: valueNSStr, location: 8, length: 1) * 6
                let q = getStringByRangeIntValue(Str: valueNSStr, location: 9, length: 1) * 3
                let S = a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q
                
                let Y = S % 11
                
                var M = "F"
                
                let JYM = "10X98765432"
                
                M = (JYM as NSString).substring(with: NSRange.init(location: Y, length: 1))
                
                let lastStr = valueNSStr.substring(with: NSRange.init(location: 17, length: 1))
                
                if lastStr == "x" {
                    if M == "X" {
                        return true
                    }else{
                        return false
                    }
                }else{
                    if M == lastStr {
                        return true
                    }else{
                        return false
                    }
                }
                
            }else{
                return false
            }
        default:
            return false
        }
    }
    
    private func getStringByRangeIntValue(Str : NSString, location : Int, length : Int) -> Int{
        
        let a = Str.substring(with: NSRange(location: location, length: length))
        
        let intValue = (a as NSString).integerValue
        
        return intValue
    }
    
}

extension String: LXSExtensionCompatible {}

// 给字符串的字面量协议增加rt前缀(包括OC的 NSString 和 NSMutableString)
public extension LXS where Base: ExpressibleByStringLiteral {
    // 截取子字符串
    func substingInRange(_ r: Range<Int>) -> String? {
        let str = base as! String // OC的 NSString 和 NSMutableString 可以强转为Swift 的 String
        if r.lowerBound < 0 || r.upperBound > str.count {
            return nil
        }
        let startIndex = str.index(str.startIndex, offsetBy:r.lowerBound)
        let endIndex   = str.index(str.startIndex, offsetBy:r.upperBound)
        return String(str[startIndex..<endIndex])
    }
    
    ///手机号加星号
    func  getSecuredPhoneNum() ->String{
        var str = base as! String
        guard str.count == 11 else {
            return ""
        }
        let start = str.index(str.startIndex, offsetBy: 3)
        let end = str.index(str.endIndex, offsetBy: -4)
//        str.replaceSubrange(start..<end, with: Array(repeating: "*", count: 4))
        str.replaceSubrange(start..<end, with: "****")

        return str
    }
    
    ///姓名脱敏
    func  getStarName() ->String{
        var str = base as! String
        guard str.count > 1 else{
           return str
        }
        let start = str.index(str.startIndex, offsetBy: 1)
        let end = str.index(str.startIndex, offsetBy: 2)
        str.replaceSubrange(start..<end, with: "*")
        return str
    }
    
    ///身份证号加星号
    func  getSecuredIdCardNum() ->String{
        var str = base as! String
        guard  str.count > 6 else {
            if str.count < 3{
                return str
            }
            //小于等于六位展示后三位，例:***111
            let end = str.index(str.endIndex, offsetBy: -3)
            str.replaceSubrange(str.startIndex..<end, with: Array(repeating: "*", count: str.count - 3))
            return str
        }
        //大陆居民和非大陆居民统一规则(保留前3后4。例:110***********3521)
        let start = str.index(str.startIndex, offsetBy: 3)
        let end = str.index(str.endIndex, offsetBy: -4)
        str.replaceSubrange(start..<end, with: Array(repeating: "*", count: str.count - 7))
        return str
    }
    
    ///地址脱敏
    func  getStarAddress() ->String{
        var str = base as! String
        guard str.count >= 7 else{
           return "*****"
        }
        let start = str.index(str.endIndex, offsetBy: -7)
        let end = str.index(str.endIndex, offsetBy: -3)
        str.replaceSubrange(start..<end, with: "****")
        return str
    }
    
    // 判断输入的字符串是否为数字，不含其它字符
    func isPurnInt() -> Bool {
        let str = base as! String
        let scan: Scanner = Scanner(string: str)
        var val:Int = 0
        return scan.scanInt(&val) && scan.isAtEnd
    }
    
    // 判断当前字符串中是否包含中文字符
    func isIncludeChinese() -> Bool {
        let str = base as! String
        for ch in str.unicodeScalars {
            // 中文字符范围：0x4e00 ~ 0x9fff
            if (0x4e00 < ch.value  && ch.value < 0x9fff) {
                return true
            }
        }
        return false
    }
    
    // 中文转拼音
    func transformToPinyin() -> String {
        let str = base as! String
        let stringRef = NSMutableString(string: str) as CFMutableString
        // 转换为带音标的拼音
        CFStringTransform(stringRef,nil, kCFStringTransformToLatin, false);
        // 去掉音标
        CFStringTransform(stringRef, nil, kCFStringTransformStripCombiningMarks, false);
        let pinyin = stringRef as String;
        
        return pinyin
    }
    
    // 转化为拼音，并移除所有空格
    // 这样转换出来的拼音字符串，每个汉字的拼音中间都会用空格隔开，增加去掉空格的函数：transformToPinyinWithoutBlank()
    func transformToPinyinWithoutBlanks() -> String {
        let str = base as! String
        let pinyin = str.lxs.transformToPinyin()
        // 去掉空格
        return pinyin.lxs.trimAllWhitespaces()
    }
    
    // 去掉首尾空格
    func trimWhitespaces() -> String {
        let str = base as! String
        let whitespace = NSCharacterSet.whitespaces
        return str.trimmingCharacters(in: whitespace)
    }
    
    // 去掉首尾空格 包括后面的换行 \n
    func trimWhitespacesAndNewlines() -> String {
        let str = base as! String
        let whitespace = NSCharacterSet.whitespacesAndNewlines
        return str.trimmingCharacters(in: whitespace)
    }

    // 去掉所有空格
    func trimAllWhitespaces() -> String {
        let str = base as! String
        return str.replacingOccurrences(of: " ", with: "", options: .literal, range: nil)
    }
    
    var md5String: String {
        let str = base as! String
        let utf8 = str.cString(using: .utf8)
        var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
        CC_MD5(utf8, CC_LONG(utf8!.count - 1), &digest)
        return digest.reduce("") { $0 + String(format:"%02X", $1) }
    }
    
    // 使用正则表达式替换
    func pregReplace(pattern: String, with: String,
                     options: NSRegularExpression.Options = []) -> String {
        /*
         常用的一些正则表达式：
         非中文：[^\\u4E00-\\u9FA5]
         非英文：[^A-Za-z]
         非数字：[^0-9]
         非中文或英文：[^A-Za-z\\u4E00-\\u9FA5]
         非英文或数字：[^A-Za-z0-9]
         非因为或数字或下划线：[^A-Za-z0-9_]
         */
        let str = base as! String
        let regex = try! NSRegularExpression(pattern: pattern, options: options)
        return regex.stringByReplacingMatches(in: str, options: [],
                                              range: NSMakeRange(0, str.count),
                                              withTemplate: with)
    }
}

extension LXS where Base: StringProtocol {
    /// range转换为NSRange
    public func nsRange(from range: Range<String.Index>) -> NSRange {
         NSRange(range, in: base)
    }
    
    public func subString(from: Int) -> String {
        if from >= base.count {
            return ""
        }
        let startIndex = base.index(base.startIndex, offsetBy: from)
        let endIndex = base.endIndex
        return String(base[startIndex..<endIndex])
    }
    
    public func subString(start: Int, end: Int) -> String {
        if start < end {
            let startIndex = base.index(base.startIndex, offsetBy: start)
            let endIndex = base.index(base.startIndex, offsetBy: end)
            
            return String(base[startIndex..<endIndex])
        }
        return ""
    }
    
    public func coverUnicode() -> String? {
        var str = base as! String
        if let range = str.range(of: "\\U") {
            str.replaceSubrange(range, with: "\\u")
        }
        guard let transformStr = str.applyingTransform(StringTransform(rawValue: "Any-Hex/Java"), reverse: true) else { return nil }
        return transformStr
    }
}

extension String {
    public func attributedString(withHighLight highLightString: String, color: UIColor) -> NSAttributedString {
        let attributedString = NSMutableAttributedString(string: self)
        
        var copyTotalString = self
        let temp = " "
        for (_, item) in highLightString.enumerated() {
            let singleString = String(item)
            if singleString == temp {
                continue
            }
            while let range = copyTotalString.range(of: singleString) {
                // 颜色如果统一的话可写在这里，如果颜色根据内容在改变，可把颜色作为参数，调用方法的时候传入
                attributedString.setAttributes([NSAttributedString.Key.foregroundColor: color], range:  NSRange(range, in: copyTotalString))
                copyTotalString = copyTotalString.replacingCharacters(in: range, with: temp)
            }
        }
        return attributedString
    }
}
